import io

import pandas as pd
import requests
from flask import Flask, request, jsonify
from qiniu import Auth

import ModelController.LinearRegressionController as linearModel
import ModelController.LogisticRegression as LRModel
from ModelController import DataDispose, qiniuAPI
from Share.regressionShare.regressionShare import retrieve_params_from_redis
from blueprints.DataDispose.DataClean import MissingValueHandler
from blueprints.Linear import useLinear
from blueprints.LogisticRegression import useLogisticRegression
from Config.Config import init_redis_client
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
from Share.Aiutility.Aitool import ai
from flask_cors import CORS

app = Flask(__name__)
app.config.from_object('Config.Config')
init_redis_client(app)
CORS(app)
app.register_blueprint(useLinear)
app.register_blueprint(useLogisticRegression)


@app.route('/LinearMain', methods=['POST'])
def linearApi():
    # 获取用户选择的参数
    featureColumns, featureColumn, test_size_user, random_state_user, train_key, test_key = retrieve_params_from_redis()
    # 获取上传的数据集（二维数组）
    # 进行数据整合test
    access_key, secret_key, bucket_name = qiniuAPI()
    q = Auth(access_key, secret_key)
    private_url_train = q.private_download_url(train_key, expires=86400)
    private_url_test = q.private_download_url(test_key, expires=86400)
    # train
    response = requests.get(private_url_train)
    df_train = pd.read_csv(io.StringIO(response.text))
    TrainData = pd.DataFrame(df_train)
    # test
    response = requests.get(private_url_test)
    df_test = pd.read_csv(io.StringIO(response.text))
    TestData = pd.DataFrame(df_test)
    # 选择模型
    predictor = linearModel.LinearRegressionPredictor()
    # 进行拟合
    predictor.fit(TrainData, test_size_user, random_state_user, featureColumns, featureColumn)
    # 进行预测 -- 预测的data是测试集数据即没有结果的数据集
    predictions = predictor.predict(TrainData, featureColumns)
    # 给出模型的性能
    evaluation = predictor.evaluate(TestData, featureColumn, featureColumns)
    for key, value in evaluation.items():
        print(f"{key}: {value}")

    response_data = {
        'train_data_preview': TrainData.head(5).to_dict(orient='records'),  # 返回训练数据的前5行
        'test_data_preview': TestData.head(5).to_dict(orient='records'),  # 返回测试数据的前5行
        'predictions': predictions.tolist(),  # 预测结果转换为列表
        'model_evaluation': evaluation  # 模型性能评估结果
    }
    # 测试
    a=1
    # 测试

    return jsonify(response_data)


@app.route("/LogisticRegressionMain", methods=['POST'])
def LogisticRegression():
    # 获取用户选择的参数
    featureColumns, featureColumn, test_size_user, random_state_user, train_key, test_key = retrieve_params_from_redis()
    # 获取上传的数据集（二维数组）
    TrainData = LRModel.readDataTrain(train_key)
    TestData = LRModel.readDataTest(test_key)
    # 选择模型
    predictor = LRModel.LogisticRegressionPredictor()
    # 进行拟合
    predictor.fit(TrainData, test_size_user, random_state_user, featureColumns, featureColumn)
    # 进行预测 -- 预测的data是测试集数据即没有结果的数据集
    predictions = predictor.predict(TrainData, featureColumns)
    # 给出模型的性能
    evaluation = predictor.evaluate(TrainData, featureColumn, featureColumns)
    print(evaluation)

    predictionsPd = pd.DataFrame(predictions, columns=['predictResult'])
    predictionsPdJson = predictionsPd.to_json(orient='records')
    return predictionsPdJson


@app.route("/DataDisposeMain", methods=['POST'])
def DataDisposeMain():
    data, dataName, typeMethod, strategy, n_neighbors = retrieve_params_from_redis()
    # 得到DataFrame数据
    dispose = DataDispose.getData(data)
    # 进行数据清理
    handler = MissingValueHandler(dispose)
    if typeMethod is not None and strategy is None and n_neighbors == 5:
        if typeMethod == 'mean':
            df_filled_mean = handler.fill_with_constant(value=None, method="mean")
            print(df_filled_mean)
        if typeMethod == 'median':
            df_filled_median = handler.fill_with_constant(method="median")
            print(df_filled_median)
        if typeMethod == 'mode':
            df_filled_mode = handler.fill_with_constant(method="mode")
            print(df_filled_mode)
    elif typeMethod is None and strategy is not None and n_neighbors == 5:
        df_filled_simpleimputer = handler.fill_with_imputer(strategy="most_frequent")
        print(df_filled_simpleimputer)
    elif typeMethod is None and strategy is None and n_neighbors == 5:
        df_filled_knn = handler.fill_with_knn(n_neighbors=5)
        print(df_filled_knn)
    else:
        df_interpolated = handler.interpolate_linear()
        print(df_interpolated)


@app.route('/ws')  # http://
def ws():
    # request.environ["wsgi.websocket"] = "Alex" #<链接>
    print("连接成功")
    user_socket = request.environ.get("wsgi.websocket")
    while 1:
        msg = user_socket.receive()
        print(msg)
        response = ai(msg)
        for chunk in response:
            print(chunk.choices[0].delta.content)
            message = chunk.choices[0].delta.content
            # print(message)
            user_socket.send(message)


if __name__ == '__main__':
    http_server = WSGIServer(("0.0.0.0", 8888), app, handler_class=WebSocketHandler)
    http_server.serve_forever()
    app.run(debug=True)
